package permission

import (
	"errors"
	"x-admin/backend/pkg/logger"

	"gorm.io/gorm"
)

// Service 权限业务逻辑层接口
type Service interface {
	Create(req *CreateRequest) (*Permission, error)
	GetByID(id uint) (*Permission, error)
	Update(id uint, req *UpdateRequest) (*Permission, error)
	Delete(id uint) error
	List(req *QueryRequest) ([]*Permission, int64, error)
	GetTree() ([]PermissionTree, error)
	GetAllPermissions() ([]*Permission, error)
}

// service 权限业务逻辑层实现
type service struct {
	repo Repository
}

// NewService 创建权限业务逻辑层
func NewService(repo Repository) Service {
	return &service{
		repo: repo,
	}
}

// Create 创建权限
func (s *service) Create(req *CreateRequest) (*Permission, error) {
	// 不再检查权限名是否已存在，允许创建同名权限
	logger.WithField("permission_name", req.Name).Info("开始创建权限")

	// 设置默认值
	status := 1
	if req.Status != nil {
		status = *req.Status
	}

	sort := 0
	if req.Sort != nil {
		sort = *req.Sort
	}

	permType := "menu"
	if req.Type != "" {
		permType = req.Type
	}

	// 计算层级
	level := 1
	if req.ParentID != nil && *req.ParentID != 0 {
		parent, err := s.repo.GetByID(*req.ParentID)
		if err != nil {
			return nil, errors.New("父权限不存在")
		}
		level = parent.Level + 1
	}

	// 设置默认显示名称
	displayName := req.DisplayName
	if displayName == "" {
		displayName = req.Name
	}

	// 处理父权限ID，0 表示根目录
	var parentID *uint
	if req.ParentID != nil {
		if *req.ParentID == 0 {
			// 根目录，设置为 0
			zero := uint(0)
			parentID = &zero
		} else {
			// 非根目录，使用实际的父权限ID
			parentID = req.ParentID
		}
	}

	permission := &Permission{
		Name:        req.Name,
		Code:        req.Code, // 使用用户提供的权限代码
		DisplayName: displayName,
		Description: req.Description,
		Path:        req.Path,
		Method:      req.Method,
		ParentID:    parentID,
		Level:       level,
		Sort:        sort,
		Type:        permType,
		Icon:        req.Icon,
		Status:      status,
	}

	if err := s.repo.Create(permission); err != nil {
		return nil, err
	}

	return permission, nil
}

// GetByID 根据ID获取权限
func (s *service) GetByID(id uint) (*Permission, error) {
	permission, err := s.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("权限不存在")
		}
		return nil, err
	}
	return permission, nil
}

// Update 更新权限
func (s *service) Update(id uint, req *UpdateRequest) (*Permission, error) {
	permission, err := s.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("权限不存在")
		}
		return nil, err
	}

	// 更新字段
	if req.Name != nil {
		// 不再检查权限名是否重复，允许同名权限
		logger.WithField("permission_id", id).WithField("new_name", *req.Name).Info("更新权限名称")
		permission.Name = *req.Name
	}

	if req.DisplayName != nil {
		if *req.DisplayName == "" {
			// 如果显示名称为空，使用权限名称
			permission.DisplayName = permission.Name
		} else {
			permission.DisplayName = *req.DisplayName
		}
	}

	if req.Description != nil {
		permission.Description = *req.Description
	}

	if req.Path != nil {
		permission.Path = *req.Path
	}

	if req.Method != nil {
		permission.Method = *req.Method
	}

	if req.ParentID != nil {
		// 验证父权限存在且不是自己
		if *req.ParentID == 0 {
			// 设置为根权限
			zero := uint(0)
			permission.ParentID = &zero
			permission.Level = 1
		} else {
			if *req.ParentID == id {
				return nil, errors.New("不能将自己设为父权限")
			}

			// 检查循环依赖：父权限不能是当前权限的子权限
			if err := s.validateParentPermission(id, *req.ParentID); err != nil {
				return nil, err
			}

			parent, err := s.repo.GetByID(*req.ParentID)
			if err != nil {
				return nil, errors.New("父权限不存在")
			}
			permission.ParentID = req.ParentID
			permission.Level = parent.Level + 1
		}
	}

	if req.Type != nil {
		permission.Type = *req.Type
	}

	if req.Icon != nil {
		permission.Icon = *req.Icon
	}

	if req.Sort != nil {
		permission.Sort = *req.Sort
	}

	if req.Status != nil {
		permission.Status = *req.Status
	}
	if req.Code != nil {
		permission.Code = *req.Code
	}

	if err := s.repo.Update(permission); err != nil {
		return nil, err
	}

	return permission, nil
}

// Delete 删除权限
func (s *service) Delete(id uint) error {
	permission, err := s.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("权限不存在")
		}
		return err
	}

	// 检查是否有子权限
	children, err := s.repo.GetChildrenByParentID(permission.ID)
	if err != nil {
		return err
	}
	if len(children) > 0 {
		return errors.New("存在子权限，无法删除")
	}

	return s.repo.Delete(permission.ID)
}

// List 获取权限列表
func (s *service) List(req *QueryRequest) ([]*Permission, int64, error) {
	// 设置默认分页参数
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}
	if req.PageSize > 100 {
		req.PageSize = 100
	}

	return s.repo.List(req)
}

// GetTree 获取权限树
func (s *service) GetTree() ([]PermissionTree, error) {
	permissions, err := s.repo.GetTree()
	if err != nil {
		return nil, err
	}
	return s.buildPermissionTree(permissions, nil), nil
}

// buildPermissionTree 构建权限树
func (s *service) buildPermissionTree(permissions []*Permission, parentID *uint) []PermissionTree {
	var tree []PermissionTree

	for _, perm := range permissions {
		// 判断是否为当前层级的节点
		// 根节点：parentID == nil 且 perm.ParentID == 0
		// 子节点：parentID != nil 且 perm.ParentID == parentID
		isRootNode := parentID == nil && perm.ParentID != nil && *perm.ParentID == 0
		isChildNode := parentID != nil && perm.ParentID != nil && *perm.ParentID == *parentID

		if isRootNode || isChildNode {
			//防止递归死循环
			if parentID != nil && perm.ID == *parentID {
				continue
			}
			node := PermissionTree{
				ID:          perm.ID,
				Name:        perm.Name,
				Code:        perm.Code,
				DisplayName: perm.DisplayName,
				Description: perm.Description,
				Path:        perm.Path,
				Method:      perm.Method,
				ParentID:    perm.ParentID,
				Level:       perm.Level,
				Sort:        perm.Sort,
				Type:        perm.Type,
				Icon:        perm.Icon,
				Status:      perm.Status,
				CreatedAt:   perm.CreatedAt,
				UpdatedAt:   perm.UpdatedAt,
				Children:    s.buildPermissionTree(permissions, &perm.ID),
			}
			tree = append(tree, node)
		}
	}

	return tree
}

// GetAllPermissions 获取所有权限
func (s *service) GetAllPermissions() ([]*Permission, error) {
	return s.repo.GetAllPermissions()
}

// validateParentPermission 验证父权限设置是否会造成循环依赖
func (s *service) validateParentPermission(currentID, parentID uint) error {
	// 检查要设置的父权限是否是当前权限的子权限（直接或间接）
	return s.isDescendant(currentID, parentID, make(map[uint]bool))
}

// isDescendant 检查targetID是否是currentID的子权限（直接或间接）
func (s *service) isDescendant(currentID, targetID uint, visited map[uint]bool) error {
	// 防止无限递归
	if visited[currentID] {
		return nil
	}
	visited[currentID] = true

	// 获取currentID的所有直接子权限
	children, err := s.repo.GetChildrenByParentID(currentID)
	if err != nil {
		return err
	}

	// 检查每个子权限
	for _, child := range children {
		// 如果找到目标权限，说明targetID是currentID的子权限
		if child.ID == targetID {
			return errors.New("不能将子权限设为父权限，这会造成循环依赖")
		}

		// 递归检查子权限的子权限
		if err := s.isDescendant(child.ID, targetID, visited); err != nil {
			return err
		}
	}

	return nil
}
